package com.hzit.mmcb.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hzit.common.exception.Assert;
import com.hzit.common.result.ResponseEnum;
import com.hzit.mmcb.core.enums.LendStatusEnum;
import com.hzit.mmcb.core.enums.TransTypeEnum;
import com.hzit.mmcb.core.hfb.FormHelper;
import com.hzit.mmcb.core.hfb.HfbConst;
import com.hzit.mmcb.core.hfb.RequestHelper;
import com.hzit.mmcb.core.pojo.entity.*;
import com.hzit.mmcb.core.mapper.LendItemMapper;
import com.hzit.mmcb.core.pojo.vo.InvestVO;
import com.hzit.mmcb.core.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzit.mmcb.core.utils.LendNoUtils;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author ljh
 * @since 2024-08-27
 */
@Service
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {
    @Autowired
    private LendService lendService;
    @Autowired
    private UserAccountService userAccountService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private TransFlowService transFlowService;

    /**
     * 投资生成流水与表单
     * @param vo
     * @return
     */
    @Override
    public String commitInvest(InvestVO vo) {
        //获取标的信息
        Lend lend = lendService.getById(vo.getLendId());
        //标的状态必须为募资中
        Assert.isTrue(
                lend.getStatus().intValue() == LendStatusEnum.INVEST_RUN.getStatus
                        ().intValue(),
                ResponseEnum.LEND_INVEST_ERROR);
        //标的不能超卖：(已投⾦额 + 本次投资⾦额 )>=标的⾦额（超卖）
        BigDecimal sum = lend.getInvestAmount().add(new BigDecimal(vo.getInvestAmount()));
        Assert.isTrue(sum.doubleValue() <= lend.getAmount().doubleValue(),
                ResponseEnum.LEND_FULL_SCALE_ERROR);
        //账户可⽤余额充⾜：当前⽤户的余额 >= 当前⽤户的投资⾦额（可以投资）
        Long investUserId = vo.getInvestUserId();
        BigDecimal amount = userAccountService.getAccount(investUserId);//当前⽤户的账户余额
        Assert.isTrue(amount.doubleValue() >= Double.parseDouble(vo.getInvestAmount()),
                ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);


        //生成流水
        LendItem lendItem=new LendItem();
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo);
        lendItem.setLendId(vo.getLendId());
        lendItem.setInvestUserId(vo.getInvestUserId());
        lendItem.setInvestName(vo.getInvestName());
        lendItem.setInvestAmount(new BigDecimal(vo.getInvestAmount()));
        lendItem.setLendYearRate(lend.getLendYearRate());
        lendItem.setLendStartDate(lend.getLendStartDate());
        lendItem.setLendEndDate(lend.getLendEndDate());
        lendItem.setInvestTime(LocalDateTime.now());
        BigDecimal interestCount = userAccountService.getInterestCount(new BigDecimal(vo.getInvestAmount()), lend.getLendYearRate(), lend.getPeriod(), lend.getReturnMethod());
        lendItem.setExpectAmount(interestCount);
        lendItem.setRealAmount(new BigDecimal(0));
        lendItem.setStatus(0);
        this.save(lendItem);
        //投资人信息
        UserInfo voteUserInfo = userInfoService.getById(vo.getInvestUserId());
        //借款人信息
        UserInfo benefit = userInfoService.getById(lend.getUserId());
        //生成表单
        Map<String, Object> map=new HashMap<>();
        map.put("agentId",HfbConst.AGENT_ID);
        map.put("voteBindCode",voteUserInfo.getBindCode());
        map.put("benefitBindCode",benefit.getBindCode());
        map.put("agentProjectCode",lend.getLendNo());
        map.put("agentProjectName",lend.getTitle());
        map.put("agentBillNo",lendItemNo);
        map.put("voteAmt",new BigDecimal(vo.getInvestAmount()));
        map.put("votePrizeAmt",new BigDecimal(0));
        map.put("voteFeeAmt",new BigDecimal(0));
        map.put("projectAmt",lend.getAmount());
        map.put("note","");
        map.put("notifyUrl",HfbConst.INVEST_NOTIFY_URL);
        map.put("returnUrl",HfbConst.INVEST_RETURN_URL);
        map.put("timestamp",RequestHelper.getTimestamp());
        map.put("sign",RequestHelper.getSign(map));
        String formStr = FormHelper.buildForm(HfbConst.INVEST_URL, map);
        return formStr;
    }

    /**
     * 投资回调
     * @param map
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String notifyAccount(Map<String, Object> map) {
        String lendItemNo = (String) map.get("agentBillNo");
        TransFlow transFlow = transFlowService.getOne(new LambdaQueryWrapper<TransFlow>().eq(TransFlow::getTransNo, lendItemNo));
        if (transFlow!=null){
            return "success";
        }
        //投资金额
        BigDecimal amt = new BigDecimal((String) map.get("voteAmt"));

        //修改标的出借记录表lendItem
        LendItem lendItem = this.getOne(new LambdaQueryWrapper<LendItem>().eq(LendItem::getLendItemNo, lendItemNo));
        lendItem.setStatus(1);
        this.updateById(lendItem);
        //修改用户账户表userAccount
        UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<UserAccount>().eq(UserAccount::getUserId, lendItem.getInvestUserId()));
        userAccount.setAmount(userAccount.getAmount().subtract(amt));
        userAccount.setFreezeAmount(userAccount.getFreezeAmount().add(amt));
        userAccountService.updateById(userAccount);

        //修改标的表
        Lend lend = lendService.getById(lendItem.getLendId());
        lend.setInvestNum(lend.getInvestNum()+1); //投资次数加一
        lend.setInvestAmount(lend.getInvestAmount().add(amt));
        lendService.updateById(lend);

        //生成流水表
        transFlow = new TransFlow();
        transFlow.setUserId(lendItem.getInvestUserId());
        transFlow.setUserName(lendItem.getInvestName());
        transFlow.setTransNo(lendItemNo);
        transFlow.setTransType(TransTypeEnum.INVEST_LOCK.getIntegral());
        transFlow.setTransTypeName(TransTypeEnum.INVEST_LOCK.getMsg());
        transFlow.setTransAmount(amt);
        transFlow.setMemo("投资项⽬编号：" + lend.getLendNo() + "，项⽬名称：" + lend.getTitle());
        transFlowService.save(transFlow);
        return "success";
    }

    @Override
    public List<LendItem> listByLendId(Long id) {
        List<LendItem> list = this.list(new LambdaQueryWrapper<LendItem>().eq(LendItem::getLendId, id));
        return list;
    }
}
